from selenium import webdriver
from selenium.webdriver.remote.errorhandler import NoSuchElementException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from pykeyboard import PyKeyboard
from PIL import Image
from PIL import ImageEnhance
from time import sleep
from pyzbar import pyzbar
from io import BytesIO

#  元素查找等待时间
ELEMENT_WAIT = 15


class Chrome:

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
        self.driver = self.open()
        self.kb = PyKeyboard()

    def open(self):
        o = webdriver.ChromeOptions()
        o.add_argument('user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36')
        #  o.add_argument('--incognito')
        if 'proxy_server' in self.__dict__:
            o.add_argument('--proxy-server=%s' % self.proxy_server())
        if 'headless' in self.__dict__ and self.headless:
            o.add_argument('--headless')
        if 'detach' in self.__dict__ and self.detach:
            o.add_experimental_option('detach', True)
        o.add_experimental_option('excludeSwitches', ['enable-automation'])
        o.add_argument('--start-maximized')
        #  o.add_argument("--no-sandbox")
        #  o.add_argument('disable-infobars')
        #  o.add_argument('--user-data-dir=/dev/shm/alipay')
        #  o.add_experimental_option("debuggerAddress", "127.0.0.1:9999")
        caps = DesiredCapabilities.CHROME
        caps['loggingPrefs'] = {'performance': 'ALL'}
        #  chrome = webdriver.Chrome(chrome_options=o)
        chrome = webdriver.Chrome(chrome_options=o, desired_capabilities=caps)
        chrome.implicitly_wait(ELEMENT_WAIT)
        return chrome

    def log(self):
        logs = self.driver.get_log('performance')
        return [x['message'] for x in logs]

    def alert_ok(self):
        try:
            self.driver.switch_to_alert().accept()
        except:
            pass

    def close(self):
        if not self.reachable() or len(self.driver.window_handles) < 2:
            return None
        self.driver.close()
        self.driver.switch_to_window(self.driver.window_handles[0])

    def urlcompare(self, url, **kwargs):
        """
        判断当前URL是否包含指定URL
        """
        mode = kwargs.pop('mode', 'start')
        if mode == 'start':
            return self.driver.current_url.lower().startswith(url.lower(), **kwargs)
        if self.driver.current_url.lower().find(url.lower()) == -1:
            return False
        return True

    def find_source(self, keyword):
        """
        查找当前源代码内容
        """
        return self.driver.page_source.find(keyword)

    def reachable(self):
        """
        判断浏览器是否存在
        """
        try:
            self.driver.window_handles
            return True
        except:
            return False

    def refresh(self):
        self.driver.refresh()
        self.alert_ok()

    def element(self, name, t='id', parent=None, more=False, default=None):
        try:
            parent = self.driver if parent is None else parent
            more = 's' if more else ''
            e = getattr(parent, 'find_element%s_by_%s' % (more, t))
            return e(name)
        except NoSuchElementException:
            return default

    def xpath(self, name, **kwargs):
        return self.element(name, 'xpath', **kwargs)

    def css(self, name, **kwargs):
        return self.element(name, 'css_selector', **kwargs)

    def qrcode(self, **kwargs):
        img = Image.open(BytesIO(self.driver.get_screenshot_as_png()))
        img = ImageEnhance.Brightness(img).enhance(2)
        img = ImageEnhance.Contrast(img).enhance(8)
        img = img.convert('L')
        qrcode = pyzbar.decode(img)
        if qrcode and qrcode[0] and isinstance(qrcode[0], pyzbar.Decoded):
            return qrcode[0].data.decode()
        return None

    def send_keys(self, name, val, t='id'):
        e = self.element(name, t)
        e.click()
        e.clear()
        e.send_keys(val)

    def sleep(self, sec):
        return sleep(sec)

    def __getattr__(self, name):
        if name in self.__dict__:
            return self.__dict__[name]
        return getattr(self.driver, name)

